home *** CD-ROM | disk | FTP | other *** search
- /* Print values for GNU debugger gdb.
- Copyright (C) 1986, 1988 Free Software Foundation, Inc.
-
- GDB is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY. No author or distributor accepts responsibility to anyone
- for the consequences of using it or for whether it serves any
- particular purpose or works at all, unless he says so in writing.
- Refer to the GDB General Public License for full details.
-
- Everyone is granted permission to copy, modify and redistribute GDB,
- but only under the conditions described in the GDB General Public
- License. A copy of this license is supposed to have been given to you
- along with GDB so you can know your rights and responsibilities. It
- should be in a file named COPYING. Among other things, the copyright
- notice and this notice must be preserved on all copies.
-
- In other words, go ahead and share GDB, but don't try to stop
- anyone else from sharing it farther. Help stamp out software hoarding!
- */
-
- #include <stdio.h>
- #include "defs.h"
- #include "symtab.h"
- #include "value.h"
-
- /* Maximum number of chars to print for a string pointer value
- or vector contents. */
-
- static int print_max;
-
- static void type_print_varspec_suffix ();
- static void type_print_varspec_prefix ();
- static void type_print_base ();
-
- char **unsigned_type_table;
- char **signed_type_table;
- char **float_type_table;
-
- /* Print the value VAL in C-ish syntax on stream STREAM.
- FORMAT is a format-letter, or 0 for print in natural format of data type.
- If the object printed is a string pointer, returns
- the number of string bytes printed. */
-
- value_print (val, stream, format)
- value val;
- FILE *stream;
- char format;
- {
- register int i, n, typelen;
-
- if (val == 0)
- {
- printf_filtered ("<address of value unknown>");
- return 0;
- }
-
- /* A "repeated" value really contains several values in a row.
- They are made by the @ operator.
- Print such values as if they were arrays. */
-
- if (VALUE_REPEATED (val))
- {
- n = VALUE_REPETITIONS (val);
- typelen = TYPE_LENGTH (VALUE_TYPE (val));
- fputc_filtered ('{', stream);
- /* Print arrays of characters using string syntax. */
- if (typelen == 1 && TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_INT
- && format == 0)
- {
- fputc_filtered ('"', stream);
- for (i = 0; i < n && i < print_max; i++)
- {
- QUIT;
- printchar (VALUE_CONTENTS (val)[i], stream);
- }
- if (i < n)
- fprintf_filtered (stream, "...");
- fputc_filtered ('"', stream);
- }
- else
- {
- for (i = 0; i < n && i < print_max; i++)
- {
- if (i)
- fprintf_filtered (stream, ", ");
- val_print (VALUE_TYPE (val), VALUE_CONTENTS (val) + typelen * i,
- VALUE_ADDRESS (val) + typelen * i, stream, format);
- }
- if (i < n)
- fprintf_filtered (stream, "...");
- }
- fputc_filtered ('}', stream);
- return n * typelen;
- }
- else
- {
- /* A simple (nonrepeated) value */
- /* If it is a pointer, indicate what it points to. */
- if (TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_PTR)
- {
- fprintf_filtered (stream, "(");
- type_print (VALUE_TYPE (val), "", stream, -1);
- fprintf_filtered (stream, ") ");
- }
- return val_print (VALUE_TYPE (val), VALUE_CONTENTS (val),
- VALUE_ADDRESS (val), stream, format);
- }
- }
-
- /* Print data of type TYPE located at VALADDR (within GDB),
- which came from the inferior at address ADDRESS,
- onto stdio stream STREAM according to FORMAT
- (a letter or 0 for natural format).
-
- If the data are a string pointer, returns the number of
- sting characters printed. */
-
- int
- val_print (type, valaddr, address, stream, format)
- struct type *type;
- char *valaddr;
- CORE_ADDR address;
- FILE *stream;
- char format;
- {
- register int i;
- int len;
- struct type *elttype;
- int eltlen;
- int val;
- unsigned char c;
-
- QUIT;
-
- switch (TYPE_CODE (type))
- {
- case TYPE_CODE_ARRAY:
- if (TYPE_LENGTH (type) >= 0)
- {
- elttype = TYPE_TARGET_TYPE (type);
- eltlen = TYPE_LENGTH (elttype);
- len = TYPE_LENGTH (type) / eltlen;
- fprintf_filtered (stream, "{");
- /* For an array of chars, print with string syntax. */
- if (eltlen == 1 && TYPE_CODE (elttype) == TYPE_CODE_INT
- && format == 0)
- {
- fputc_filtered ('"', stream);
- for (i = 0; i < len && i < print_max; i++)
- {
- QUIT;
- printchar (valaddr[i], stream);
- }
- if (i < len)
- fprintf_filtered (stream, "...");
- fputc_filtered ('"', stream);
- }
- else
- {
- for (i = 0; i < len && i < print_max; i++)
- {
- if (i) fprintf_filtered (stream, ", ");
- val_print (elttype, valaddr + i * eltlen,
- 0, stream, format);
- }
- if (i < len)
- fprintf_filtered (stream, "...");
- }
- fprintf_filtered (stream, "}");
- break;
- }
- /* Array of unspecified length: treat like pointer. */
- valaddr = (char *) &address;
-
- case TYPE_CODE_PTR:
- if (format)
- {
- print_scalar_formatted (valaddr, type, format, 0, stream);
- break;
- }
- fprintf_filtered (stream, "0x%x", * (int *) valaddr);
- /* For a pointer to char or unsigned char,
- also print the string pointed to, unless pointer is null. */
-
- /* For an array of chars, print with string syntax. */
- elttype = TYPE_TARGET_TYPE (type);
- if (TYPE_LENGTH (elttype) == 1 && TYPE_CODE (elttype) == TYPE_CODE_INT
- && format == 0
- && unpack_long (type, valaddr) != 0)
- {
- fputc_filtered (' ', stream);
- fputc_filtered ('"', stream);
- for (i = 0; i < print_max; i++)
- {
- QUIT;
- read_memory (unpack_long (type, valaddr) + i, &c, 1);
- if (c == 0)
- break;
- printchar (c, stream);
- }
- fputc_filtered ('"', stream);
- if (i == print_max)
- fprintf_filtered (stream, "...");
- fflush (stream);
- /* Return number of characters printed, plus one for the
- terminating null if we have "reached the end". */
- return i + (print_max && i != print_max);
- }
- break;
-
- case TYPE_CODE_STRUCT:
- case TYPE_CODE_UNION:
- fprintf_filtered (stream, "{");
- len = TYPE_NFIELDS (type);
- for (i = 0; i < len; i++)
- {
- if (i) fprintf_filtered (stream, ", ");
- fprintf_filtered (stream, "%s = ", TYPE_FIELD_NAME (type, i));
- if (TYPE_FIELD_PACKED (type, i))
- {
- val = unpack_field_as_long (type, valaddr, i);
- val_print (TYPE_FIELD_TYPE (type, i), &val, 0, stream, format);
- }
- else
- val_print (TYPE_FIELD_TYPE (type, i),
- valaddr + TYPE_FIELD_BITPOS (type, i) / 8,
- 0, stream, format);
- }
- fprintf_filtered (stream, "}");
- break;
-
- case TYPE_CODE_ENUM:
- if (format)
- {
- print_scalar_formatted (valaddr, type, format, 0, stream);
- break;
- }
- len = TYPE_NFIELDS (type);
- val = unpack_long (builtin_type_int, valaddr);
- for (i = 0; i < len; i++)
- {
- QUIT;
- if (val == TYPE_FIELD_VALUE (type, i))
- break;
- }
- if (i < len)
- fprintf_filtered (stream, "%s", TYPE_FIELD_NAME (type, i));
- else
- fprintf_filtered (stream, "%d", val);
- break;
-
- case TYPE_CODE_FUNC:
- if (format)
- {
- print_scalar_formatted (valaddr, type, format, 0, stream);
- break;
- }
- fprintf_filtered (stream, "{");
- type_print (type, "", stream, -1);
- fprintf_filtered (stream, "} ");
- fprintf_filtered (stream, "0x%x", address);
- break;
-
- case TYPE_CODE_INT:
- if (format)
- {
- print_scalar_formatted (valaddr, type, format, 0, stream);
- break;
- }
- fprintf_filtered (stream,
- TYPE_UNSIGNED (type) ? "%u" : "%d",
- unpack_long (type, valaddr));
- if (TYPE_LENGTH (type) == 1)
- {
- fprintf_filtered (stream, " '");
- printchar (unpack_long (type, valaddr), stream);
- fputc_filtered ('\'', stream);
- }
- break;
-
- case TYPE_CODE_FLT:
- if (format)
- {
- print_scalar_formatted (valaddr, type, format, 0, stream);
- break;
- }
- #ifdef IEEE_FLOAT
- if (is_nan (unpack_double (type, valaddr)))
- {
- fprintf_filtered (stream, "Nan");
- break;
- }
- #endif
- fprintf_filtered (stream, "%g", unpack_double (type, valaddr));
- break;
-
- case TYPE_CODE_VOID:
- fprintf_filtered (stream, "void");
- break;
-
- default:
- error ("Invalid type code in symbol table.");
- }
- fflush (stream);
- return 0;
- }
-
- #ifdef IEEE_FLOAT
-
- union ieee {
- int i[2];
- double d;
- };
-
- /* Nonzero if ARG (a double) is a NAN. */
-
- int
- is_nan (arg)
- union ieee arg;
- {
- int lowhalf, highhalf;
- union { int i; char c; } test;
-
- /* Separate the high and low words of the double.
- Distinguish big and little-endian machines. */
- test.i = 1;
- if (test.c != 1)
- /* Big-endian machine */
- lowhalf = arg.i[1], highhalf = arg.i[0];
- else
- lowhalf = arg.i[0], highhalf = arg.i[1];
-
- /* Nan: exponent is the maximum possible, and fraction is nonzero. */
- return (((highhalf>>20) & 0x7ff) == 0x7ff
- &&
- ! ((highhalf & 0xfffff == 0) && (lowhalf == 0)));
- }
- #endif
-
- /* Print a description of a type TYPE
- in the form of a declaration of a variable named VARSTRING.
- Output goes to STREAM (via stdio).
- If SHOW is positive, we show the contents of the outermost level
- of structure even if there is a type name that could be used instead.
- If SHOW is negative, we never show the details of elements' types. */
-
- type_print (type, varstring, stream, show)
- struct type *type;
- char *varstring;
- FILE *stream;
- int show;
- {
- type_print_1 (type, varstring, stream, show, 0);
- }
-
- /* LEVEL is the depth to indent lines by. */
-
- type_print_1 (type, varstring, stream, show, level)
- struct type *type;
- char *varstring;
- FILE *stream;
- int show;
- int level;
- {
- register enum type_code code;
- type_print_base (type, stream, show, level);
- code = TYPE_CODE (type);
- if ((varstring && *varstring)
- ||
- /* Need a space if going to print stars or brackets;
- but not if we will print just a type name. */
- ((show > 0 || TYPE_NAME (type) == 0)
- &&
- (code == TYPE_CODE_PTR || code == TYPE_CODE_FUNC
- || code == TYPE_CODE_ARRAY)))
- fprintf_filtered (stream, " ");
- type_print_varspec_prefix (type, stream, show, 0);
- fprintf_filtered (stream, "%s", varstring);
- type_print_varspec_suffix (type, stream, show, 0);
- }
-
- /* Print any asterisks or open-parentheses needed before the
- variable name (to describe its type).
-
- On outermost call, pass 0 for PASSED_A_PTR.
- On outermost call, SHOW > 0 means should ignore
- any typename for TYPE and show its details.
- SHOW is always zero on recursive calls. */
-
- static void
- type_print_varspec_prefix (type, stream, show, passed_a_ptr)
- struct type *type;
- FILE *stream;
- int show;
- int passed_a_ptr;
- {
- if (type == 0)
- return;
-
- if (TYPE_NAME (type) && show <= 0)
- return;
-
- QUIT;
-
- switch (TYPE_CODE (type))
- {
- case TYPE_CODE_PTR:
- type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 1);
- fputc_filtered ('*', stream);
- break;
-
- case TYPE_CODE_FUNC:
- case TYPE_CODE_ARRAY:
- type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 0);
- if (passed_a_ptr)
- fputc_filtered ('(', stream);
- break;
-
- default:
- break;
- }
- }
-
- /* Print any array sizes, function arguments or close parentheses
- needed after the variable name (to describe its type).
- Args work like type_print_varspec_prefix. */
-
- static void
- type_print_varspec_suffix (type, stream, show, passed_a_ptr)
- struct type *type;
- FILE *stream;
- int show;
- int passed_a_ptr;
- {
- if (type == 0)
- return;
-
- if (TYPE_NAME (type) && show <= 0)
- return;
-
- QUIT;
-
- switch (TYPE_CODE (type))
- {
- case TYPE_CODE_ARRAY:
- if (passed_a_ptr)
- fprintf_filtered (stream, ")");
- fprintf_filtered (stream, "[");
- if (TYPE_LENGTH (type) >= 0)
- fprintf_filtered (stream, "%d",
- TYPE_LENGTH (type) / TYPE_LENGTH (TYPE_TARGET_TYPE (type)));
- fprintf_filtered (stream, "]");
- type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 0);
- break;
-
- case TYPE_CODE_PTR:
- type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 1);
- break;
-
- case TYPE_CODE_FUNC:
- type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0,
- passed_a_ptr);
- if (passed_a_ptr)
- fprintf_filtered (stream, ")");
- fprintf_filtered (stream, "()");
- break;
-
- default:
- break;
- }
- }
-
- /* Print the name of the type (or the ultimate pointer target,
- function value or array element), or the description of a
- structure or union.
-
- SHOW nonzero means don't print this type as just its name;
- show its real definition even if it has a name.
- SHOW zero means print just typename or struct tag if there is one
- SHOW negative means abbreviate structure elements.
- SHOW is decremented for printing of structure elements.
-
- LEVEL is the depth to indent by.
- We increase it for some recursive calls. */
-
- static void
- type_print_base (type, stream, show, level)
- struct type *type;
- FILE *stream;
- int show;
- int level;
- {
- char *name;
- register int i;
- register int len;
- register int lastval;
-
- QUIT;
-
- if (type == 0)
- {
- fprintf_filtered (stream, "type unknown");
- return;
- }
-
- if (TYPE_NAME (type) && show <= 0)
- {
- fprintf_filtered (stream, TYPE_NAME (type));
- return;
- }
-
- switch (TYPE_CODE (type))
- {
- case TYPE_CODE_ARRAY:
- case TYPE_CODE_PTR:
- case TYPE_CODE_FUNC:
- type_print_base (TYPE_TARGET_TYPE (type), stream, show, level);
- break;
-
- case TYPE_CODE_STRUCT:
- fprintf_filtered (stream, "struct ");
- goto struct_union;
-
- case TYPE_CODE_UNION:
- fprintf_filtered (stream, "union ");
- struct_union:
- if (TYPE_NAME (type) && (name = TYPE_NAME (type)))
- {
- while (*name != ' ') name++;
- fprintf_filtered (stream, "%s ", name + 1);
- }
- if (show < 0)
- fprintf_filtered (stream, "{...}");
- else
- {
- fprintf_filtered (stream, "{");
- len = TYPE_NFIELDS (type);
- if(len)
- fprintf_filtered (stream, "\n");
- else
- fprintf_filtered(stream, "<no data fields>\n");
- for (i = 0; i < len; i++)
- {
- QUIT;
- print_spaces (level + 4, stream);
-
- /* If this is a bit-field and there is a gap before it,
- print a nameless field to account for the gap. */
-
- if (TYPE_FIELD_PACKED (type, i))
- {
- int gap = (TYPE_FIELD_BITPOS (type, i)
- - (i > 0
- ? (TYPE_FIELD_BITPOS (type, i - 1)
- + (TYPE_FIELD_PACKED (type, i - 1)
- ? TYPE_FIELD_BITSIZE (type, i - 1)
- : TYPE_LENGTH (TYPE_FIELD_TYPE (type, i - 1)) * 8))
- : 0));
- if (gap != 0)
- {
- fprintf_filtered (stream, "int : %d;\n", gap);
- print_spaces (level + 4, stream);
- }
- }
-
- /* Print the declaration of this field. */
-
- type_print_1 (TYPE_FIELD_TYPE (type, i),
- TYPE_FIELD_NAME (type, i),
- stream, show - 1, level + 4);
-
- /* Print the field width. */
-
- if (TYPE_FIELD_PACKED (type, i))
- fprintf_filtered (stream, " : %d", TYPE_FIELD_BITSIZE (type, i));
-
- fprintf_filtered (stream, ";\n");
- }
- print_spaces (level, stream);
- fputc_filtered ('}', stream);
- }
- break;
-
- case TYPE_CODE_ENUM:
- fprintf_filtered (stream, "enum ");
- if (TYPE_NAME (type))
- {
- name = TYPE_NAME (type);
- while (*name != ' ') name++;
- fprintf_filtered (stream, "%s ", name + 1);
- }
- if (show < 0)
- fprintf_filtered (stream, "{...}");
- else
- {
- fprintf_filtered (stream, "{");
- len = TYPE_NFIELDS (type);
- lastval = 0;
- for (i = 0; i < len; i++)
- {
- QUIT;
- if (i) fprintf_filtered (stream, ", ");
- fprintf_filtered (stream, "%s", TYPE_FIELD_NAME (type, i));
- if (lastval != TYPE_FIELD_VALUE (type, i))
- {
- fprintf_filtered (stream, " : %d", TYPE_FIELD_VALUE (type, i));
- lastval = TYPE_FIELD_VALUE (type, i);
- }
- lastval++;
- }
- fprintf_filtered (stream, "}");
- }
- break;
-
- case TYPE_CODE_INT:
- if (TYPE_UNSIGNED (type))
- name = unsigned_type_table[TYPE_LENGTH (type)];
- else
- name = signed_type_table[TYPE_LENGTH (type)];
- fprintf_filtered (stream, "%s", name);
- break;
-
- case TYPE_CODE_FLT:
- name = float_type_table[TYPE_LENGTH (type)];
- fprintf_filtered (stream, "%s", name);
- break;
-
- case TYPE_CODE_VOID:
- fprintf_filtered (stream, "void");
- break;
-
- case 0:
- fprintf_filtered (stream, "struct unknown");
- break;
-
- default:
- error ("Invalid type code in symbol table.");
- }
- }
-
- static void
- set_maximum_command (arg)
- char *arg;
- {
- if (!arg) error_no_arg ("value for maximum elements to print");
- print_max = atoi (arg);
- }
-
- void
- initialize_valprint ()
- {
- add_com ("set-maximum", class_vars, set_maximum_command,
- "Set NUMBER as limit on string chars or array elements to print.");
-
- print_max = 200;
-
- unsigned_type_table
- = (char **) xmalloc ((1 + sizeof (unsigned long)) * sizeof (char *));
- bzero (unsigned_type_table, (1 + sizeof (unsigned long)));
- unsigned_type_table[sizeof (unsigned char)] = "unsigned char";
- unsigned_type_table[sizeof (unsigned short)] = "unsigned short";
- unsigned_type_table[sizeof (unsigned long)] = "unsigned long";
- unsigned_type_table[sizeof (unsigned int)] = "unsigned int";
-
- signed_type_table
- = (char **) xmalloc ((1 + sizeof (long)) * sizeof (char *));
- bzero (signed_type_table, (1 + sizeof (long)));
- signed_type_table[sizeof (char)] = "char";
- signed_type_table[sizeof (short)] = "short";
- signed_type_table[sizeof (long)] = "long";
- signed_type_table[sizeof (int)] = "int";
-
- float_type_table
- = (char **) xmalloc ((1 + sizeof (double)) * sizeof (char *));
- bzero (float_type_table, (1 + sizeof (double)));
- float_type_table[sizeof (float)] = "float";
- float_type_table[sizeof (double)] = "double";
- }
-